# -*- coding: utf-8 -*-
"""
@Time    : 2024/8/6 20:05
@Author  : Gaoxuming
@FileName: segyv1.2.py
@Software: PyCharm
@Doc     : To process seismic(binary segy) data and conduct statistical analysis
"""
import os
import sys

import numpy as np
import segyio
import matplotlib.pyplot as plt
from prettytable import PrettyTable
import tkinter as tk
from tkinter import ttk, font
import pandas as pd
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

# ANSI escape codes for text formatting
RESET = "\033[0m"
BRIGHT = "\033[1m"
GREEN = "\033[32m"
RED = "\033[91m"
BLUE = "\033[94m"


def compare_segy_files(file1, file2, error_threshold=1e-5, relative_error_threshold=0.001):
    """
    :param file1: arm segy文件所在路径，可以为绝对路径，也可以为脚本执行的相对路径
    :param file2: x86 segy文件所在路径，可以为绝对路径，也可以为脚本执行的相对路径
    :param start_trace: 开始比较的迹线编号，默认为0
    :param error_threshold: 绝对误差阈值
    :param relative_error_threshold: 相对误差阈值
    """
    # 比较文件大小
    size1 = os.path.getsize(file1)
    size2 = os.path.getsize(file2)

    print(f'{BRIGHT}文件 {BLUE}{file1}{RESET} 大小: {GREEN}{size1}{RESET} 字节')
    print(f'{BRIGHT}文件 {BLUE}{file2}{RESET} 大小: {GREEN}{size2}{RESET} 字节')
    # 检查文件大小是否一致
    if size1 == size2:
        print(f'{BRIGHT}{GREEN}文件大小一致{RESET}')
    else:
        print(f'{BRIGHT}{RED}文件大小不一致{RESET}')

    print('====' * 30)

    with segyio.open(file1, "r", endian='little', ignore_geometry=True) as segy1, segyio.open(file2, "r",
                                                                                              endian='little',
                                                                                              ignore_geometry=True) as segy2:
        # 读取所有迹线数据并转换为 NumPy 数组
        traces1 = np.array([trace for trace in segy1.trace[:]])
        # 读取所有迹线数据并转换为 NumPy 数组
        traces2 = np.array([trace for trace in segy2.trace[:]])

        binary_header1 = segy1.bin
        # 打印二进制文件头
        print(f'{BRIGHT}文件 {BLUE}{file1}{RESET} 二进制文件头:{RESET}\n{binary_header1}')

        binary_header2 = segy2.bin
        # 打印二进制文件头
        print(f'{BRIGHT}文件 {BLUE}{file2}{RESET} 二进制文件头:{RESET}\n{binary_header2}')

        # 检查二进制文件头是否一致
        if binary_header1 == binary_header2:
            print(f'{BRIGHT}{GREEN}二进制文件头一致{RESET}')
        else:
            print(f'{BRIGHT}{RED}二进制文件头不一致{RESET}')
        # 比较每个迹线的道头信息
        header_diff = []
        # 确保两个文件中的迹线数量相同
        if segy1.tracecount == segy2.tracecount:
            for trace_index in range(segy1.tracecount):
                header_1 = segy1.header[trace_index]
                header_2 = segy2.header[trace_index]
                if header_1 != header_2:
                    header_diff.append(trace_index)
                    # print(f"Trace headers 在索引 {trace_index} 处不一致！")
                    # print(f'不一致的Trac headers 信息为：')
                    # print(f"文件 {BLUE}{file1}{RESET} : {header_1}")
                    # print(f"文件 {BLUE}{file2}{RESET} : {header_2}")
            # print(f"header diff list ：\n{header_diff}")
        else:
            print("两个文件的trace num不一致！")
            print(f"文件 {BLUE}{file1}{RESET} trace num： {RED}{segy1.tracecount}{RESET} ")
            print(f"文件 {BLUE}{file2}{RESET} trace num： {RED}{segy2.tracecount}{RESET} ")

    print('====' * 30)
    # 计算绝对误差
    absolute_error = np.abs(np.abs(traces1) - np.abs(traces2))
    # 计算绝对值较大者
    absolute_max = np.maximum(np.abs(traces1), np.abs(traces2))
    # absolute_max = (np.abs(traces1) if np.abs(traces1) >= np.abs(traces2) else np.abs(traces2))
    # 计算相对误差，除数为零时置相对误差为零
    relative_error = (np.abs(absolute_error / (absolute_max + 1e-10)))
    # relative_error = np.where(absolute_max != 0, np.abs(absolute_error / absolute_max), 0)
    # relative_error = ((np.abs(absolute_error / absolute_max)) if absolute_max else 0)  # 防止分母为零
    # 最大差值
    max_diff_sample = np.max(absolute_error)
    # 道数量
    trace_num_arm = segy1.tracecount
    trace_num_x86 = segy2.tracecount
    # 样本数量
    sample_num_arm = len(traces1) * len(traces1[0])
    sample_num_x86 = len(traces2) * len(traces2[0])
    # 相同样点矩阵
    same_sample_mask1 = (absolute_error <= error_threshold)
    # 相同样点数量
    same_sample_count1 = np.count_nonzero(same_sample_mask1)

    # 不同样点矩阵
    diff_sample_mask = (absolute_error > error_threshold)

    # 相同样点矩阵
    same_sample_mask2 = ((relative_error <= relative_error_threshold) & diff_sample_mask)
    # 相同样点数量
    same_sample_count2 = np.count_nonzero(same_sample_mask2)

    # 不同样点矩阵
    diff_sample_mask2 = ((relative_error > relative_error_threshold) & diff_sample_mask)
    # 不同样点数量
    diff_sample_count = np.count_nonzero(diff_sample_mask2)
    same_sample_count = same_sample_count1 + same_sample_count2
    print(
        f'{BRIGHT}在绝对误差 {RED}{error_threshold}{RESET} 和相对误差 {RED}{relative_error_threshold * 100}% {RESET}范围下：')
    print(f"trace        num : {GREEN}{trace_num_arm}{RESET}")
    print(f"total sample num : {GREEN}{sample_num_arm}{RESET}")
    print(f"same  sample num : {GREEN}{same_sample_count}{RESET}")
    print(f"diff  sample num : {RED}{diff_sample_count}{RESET}")
    print(f"max   diff sample: {RED}{max_diff_sample}{RESET}")

    if header_diff:
        print(f"total header num : {GREEN}{segy1.tracecount}{RESET}")
        print(f"same header  num : {GREEN}{segy1.tracecount - len(header_diff)}{RESET}")
        print(f"diff header  num : {RED}{len(header_diff)}{RESET} ")
    else:
        print(f"total header num : {GREEN}{segy1.tracecount}{RESET}")
        print(f"same header  num : {GREEN}{segy1.tracecount}{RESET}")
        print(f"diff header  num : {RED}0{RESET} ")
    # 创建表格
    table = PrettyTable()
    table.field_names = ["统计指标", "值"]
    # 设置列的最大宽度
    table._max_width[0] = 30  # 设置第一列的最大宽度
    table._max_width[1] = 20  # 设置第二列的最大宽度
    table.padding_width = 3  # 增加单元格内空白空间
    table.border = True  # 显示边框
    table.hrules = 1  # 显示所有水平边框
    table.vrules = 1  # 显示垂直边框
    table.align["统计指标"] = "l"  # 居中对齐统计指标列
    table.align["值"] = "l"  # 居中对齐值列

    # 添加数据行
    table.add_row(["trace        num ：", trace_num_arm])
    table.add_row(["total sample num ：", sample_num_arm])
    table.add_row(["same  sample num : ", same_sample_count])
    table.add_row(["diff  sample num : ", diff_sample_count])
    table.add_row(["max   diff sample: ", max_diff_sample])
    table.add_row(["total header num : ", segy1.tracecount])
    table.add_row(["same  header num : ", segy1.tracecount - len(header_diff)])
    table.add_row(["diff  header num : ", len(header_diff)])
    # 打印表格
    print(table)


# file1 = 'chai_08_CMPgather_standard_out_arm.segy'
# file2 = 'chai_08_CMPgather_standard_out_x86.segy'
# file3 = '11_bpfilter_BP_FILTER_SPARK_arm.segy'
# file4 = '11_bpfilter_BP_FILTER_SPARK_debug_O0test.segy'
# compare_segy_files(file1, file2)
if __name__ == '__main__':
    # 从命令行参数获取文件路径
    if len(sys.argv) < 3:
        print("请提供两个 SEG-Y 文件的路径作为参数，第一个参数为arm环境segy，第二个为x86环境segy文件")
        sys.exit(1)

    file1_path = sys.argv[1]
    file2_path = sys.argv[2]
    # 如果提供了第三个参数，则将其作为开始迹线的编号；否则，默认为0
    # start_trace = int(sys.argv[3]) if len(sys.argv) > 3 else 0

    compare_segy_files(file1_path, file2_path)
